package com.ruoyi.repn.service.impl;

import com.alibaba.fastjson2.JSON;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.RepUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ThreadLocalUtils;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.ip.IpUtils;
import com.ruoyi.repn.domain.params.OpenidParams;
import com.ruoyi.repn.domain.params.UserLoginParams;
import com.ruoyi.repn.domain.vo.OpenidVo;
import com.ruoyi.repn.mapper.RepUserMapper;
import com.ruoyi.repn.service.IRepUserService;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static com.ruoyi.common.constant.ReportConstants.*;
import static com.ruoyi.common.constant.WXConstants.*;

/**
 * 用户信息Service业务层处理
 * 
 * @author cpf
 * @date 2024-03-02
 */
@Service
public class RepUserServiceImpl implements IRepUserService 
{

    private static final Logger log = LoggerFactory.getLogger(RepUserServiceImpl.class);

    @Autowired
    private RepUserMapper repUserMapper;

    // 令牌秘钥
    @Value("${token.secret}")
    private String tokenSecret;

    @Autowired
    private RedisCache redisCache;

    /**
     * 查询用户信息
     * 
     * @param id 用户信息主键
     * @return 用户信息
     */
    @Override
    public RepUser selectRepUserById(Long id)
    {
        return repUserMapper.selectRepUserById(id);
    }

    /**
     * 查询用户信息列表
     * 
     * @param repUser 用户信息
     * @return 用户信息
     */
    @Override
    public List<RepUser> selectRepUserList(RepUser repUser)
    {
        return repUserMapper.selectRepUserList(repUser);
    }

    /**
     * 新增用户信息
     * 
     * @param repUser 用户信息
     * @return 结果
     */
    @Override
    public int insertRepUser(RepUser repUser)
    {
        repUser.setCreateTime(DateUtils.getNowDate());
        return repUserMapper.insertRepUser(repUser);
    }

    /**
     * 修改用户信息
     * 
     * @param repUser 用户信息
     * @return 结果
     */
    @Override
    public int updateRepUser(RepUser repUser)
    {
        repUser.setUpdateTime(DateUtils.getNowDate());
        return repUserMapper.updateRepUser(repUser);
    }

    /**
     * 批量删除用户信息
     * 
     * @param ids 需要删除的用户信息主键
     * @return 结果
     */
    @Override
    public int deleteRepUserByIds(Long[] ids)
    {
        return repUserMapper.deleteRepUserByIds(ids);
    }

    /**
     * 删除用户信息信息
     * 
     * @param id 用户信息主键
     * @return 结果
     */
    @Override
    public int deleteRepUserById(Long id)
    {
        return repUserMapper.deleteRepUserById(id);
    }

    /**
     * 登陆
     * @param userLoginParams 用户信息
     * @return token
     */
    @Override
    public AjaxResult login(UserLoginParams userLoginParams) {

        AjaxResult ajaxResult =  AjaxResult.success();

        //获取openid
        OpenidVo vo = getOpenid(userLoginParams.getCode());

        //用户校验
        RepUser user = verify(userLoginParams, vo.getOpenid());

        //记录用户登录信息
        recordShopLoginInfo(user.getId());

        //创建并返回JWT token
        String token = createToken(vo);

        //把用户信息存放到redis中
        storageUser(user, token);

        ajaxResult.put(Constants.TOKEN, token);
        ajaxResult.put("data",user);
        return ajaxResult;
    }

    /**
     * 构建token
     * @param vo 信息
     * @return token
     */
    private String createToken(OpenidVo vo) {
        return Jwts.builder()
                .setSubject(vo.getOpenid()) // 设置主题为openid
                .setExpiration(new Date(System.currentTimeMillis() + JWT_EXPIRATION_TIME)) // 设置过期时间
                .signWith(SignatureAlgorithm.HS512, tokenSecret) // 使用密钥签名
                .compact();
    }

    /**
     * 把用户信息存放到redis中
     * @param user 用户
     * @param token token
     */
    private void storageUser(RepUser user, String token) {
        //把用户对象转成json字符串
        String jsonUser = JSON.toJSONString(user);
        //把用户信息存入redis
        redisCache.setCacheObject(REP_USER_TOKEN + token, jsonUser, 15, TimeUnit.DAYS);
    }

    /**
     * 用户校验
     * @param userLoginParams 用户登陆信息
     * @param openid openid
     * @return 用户信息
     */
    private RepUser verify(UserLoginParams userLoginParams, String openid) {
        //根据openid查询用户信息
        RepUser user = repUserMapper.selectRepUserByOpenId(openid);
        //用户不存在
        if (user == null) {
            //注册用户
            user = createShopUser(userLoginParams, openid);
        }
        //用户存在判断用户信息
        if (user.getStatus().equals(REP_USER_STOP)) {
            //账号停用
            throw new ServiceException("该账号已停用");
        }

        return user;
    }


    /**
     * 获取openid
     * @param code 登陆获取的code
     * @return  ReqLogin
     */
    private OpenidVo getOpenid(String code) {
        //构建请求参数
        OpenidParams params = new OpenidParams();
        params.setAppid(APP_ID);
        params.setSecret(SECRET);
        params.setJs_code(code);
        params.setGrant_type(GRANT_TYPE);

        //发起请求
        String res = HttpUtils.sendGet(LOGIN_URL, params.toString());
        //JSON转换为对象
        OpenidVo vo = JSON.parseObject(res, OpenidVo.class);

        System.out.println(vo.toString());

        if (vo.getOpenid() == null){
            log.error("wx接口调用失败："+ vo.getErrmsg());
            throw new ServiceException("wx接口调用失败");
        }
        return vo;
    }


    /**
     * 退出登录
     */
    public AjaxResult logout(HttpServletRequest request) {
        // 从请求头中获取token
        String header = request.getHeader(AUTHORIZATION_HEADER);
        //截取token
        String token = header.substring(7);
        //删除redis用户信息
        redisCache.deleteObject(REP_USER_TOKEN + token);
        //删除ThreadLocal用户信息
        ThreadLocalUtils.userThreadLocal.remove();
        return AjaxResult.success();
    }




    /**
     * 注册用户
     *
     * @param userLoginParams 用户登录信息
     */
    private RepUser createShopUser(UserLoginParams userLoginParams,String openid) {
        RepUser user = new RepUser();
        //随机创建账号
        //openid
        user.setOpenId(openid);
        //用户昵称
        user.setNickName(userLoginParams.getNickName());
        //头像
        user.setAvatarUrl(userLoginParams.getAvatarUrl());
        //性别
        user.setGender(userLoginParams.getGender());
        //用户账号状态
        user.setStatus(REP_USER_NORMAL);
        //添加用户
        repUserMapper.insertRepUser(user);
        return user;
    }


    /**
     * 记录用户登录信息
     *
     * @param userId 用户ID
     */
    private void recordShopLoginInfo(Long userId) {
        RepUser repUser = new RepUser();
        repUser.setId(userId);
        repUser.setLoginIp(IpUtils.getIpAddr());
        repUser.setLoginTime(DateUtils.getNowDate());
        repUserMapper.updateRepUser(repUser);
    }

}
